# 函数可以调用其他函数
def story():
    print("用户故事")
    return "小白兔吃萝卜,"
def tell():
    s = story()
    return s + "带上好健康一起吃"
# print(tell()) # 调用并且打印这个函数
"""
用户故事"
小白兔吃萝卜,带上好健康一起吃
"""

# 自己调用自己，但是没有出口，所以会报错
def tell_story():
    print("从前有座山")
    print("上山有座庙")
    print("庙里有个老健康")
    print("在给小健康讲故事")
    print("讲的是什么呢？")
    tell_story() # 自己又调用了自己
# tell_story()

# 递归需要注意：
"""
1、必须要有出口，每次递归都像出口靠近 这种我们成为回溯
2、往回一层一层推算结果  这种我们称为：递推
"""
# 案例一：计算从x开始到10内的和
def text1(i):
    if i == 10:
        return 10
    else:
        return i+text1(i+1)
# r = text1(1)
# print(r)# 1+2+3+4+5+6+7+8+9+10
# 每次递归后，都会开辟一个新的栈帧空间，直到达到结果，触底反弹
# 案例二：计算x整数以内的和
def sum2(x):
    if x >1:
        value = x + sum2(x- 1)
    else:
        value = 1
    return value
# print(sum2(10)) # 55
# print(sum2) # 它也一样是地址值，没有带()就不能算调用
# 匿名函数
# 以下返回的是地址值
"""print(lambda x, y: x + y)
print(lambda x, y: x + y())
print(lambda x, y: x + y(1, 2))"""
# 调用：匿名函数的精髓就是没有名字 为其绑定名字是没有意义的
# a = lambda x, y: x + y # 赋值一个名字，去调用
# print(a(1,2))

#匿名函数和内置函数一起使用
salarics={
    'xiaolong3':300000,
    'xiaolong4':3000,
    'long1':1000,
}
#比较以下薪资求薪资最高的那个人名
# 用max内置函数，比较的是ascii码值，所以不对
# print(max(salarics)) #

# 这个函数需要获得字典的value 这样才会比较value
def func(name):
    """
    :param name: 通过这个方法，来获取每一个value值
    :return:
    """
    return salarics[name]
# print(max(salarics,key=func)) # key是一个形参，用它的value来去比对每一个键

#求最大值：转化成匿名函数
print(max(salarics, key=lambda name: salarics[name]))

# 求最小值：匿名函数
# print(min(salarics, key = lambda  name:salarics[name]))

# 闭包函数
def outer():
    print("外面的函数正在运行")
    def inner():
        print("里面的函数正在运行")
    return inner # 欠它一个()
"""inner = outer() # 此时 inner  == inner，没有调用
inner() # 调用"""
# outer()() # 这样补上去也可以，但不建议这么用
"""
外面的函数这个在运行
里面的函数正在运行
"""
def aa():
    a = 10 # 外函数定义了一个10
    def bb():
        nonlocal a # 修改函数内的变量值
        a = 99
        print(f"bb函数的a值是：{a}") # 99
        """
        局部变量>全局变量
        我想在局部变量里，修改a的值
        """
    print(f"aa函数的a值是：{a}")
    def cc():
        print(f"cc函数的a值是：{a}")
    return bb(),cc()
# aa()
"""
外函数的a值是：10
内函数的a值是：99
cc函数的a值是：99
"""
def a():
    print("我是a函数")
    def b():
        print("我是b函数")
        def c():
            print("我是c函数")
        c()
    b()
    print("lalala")
    print("我是很健康")
    def e():
        print("我是e函数")
        def g():
            print("我是g函数")
    print("啦啦啦")
    e()
    def p():
        print("我是p函数")
    p() # 直接调用，不带()，是返回地址值
# a()
"""
代码运行：
1、我是a函数
2、我是b函数
3、我是c函数
4、lalala
5、我是很健康
6、啦啦啦
7、我是e函数
8、我是p函数
"""

# 闭包案例：自增长函数，每次调用它的时候，自己+1
def auto_num(num):
    def add():
        nonlocal num # 修改局部变量的值
        num+=1 # 每次局部变量的num+1
        return num # 子函数返回num值
    return add # 外函数返回的是子函数地址值，锁住地址值比较关键
# 郝健成就相当于 add
# add是怎么来的
# add是一个函数，函数里面修改了局部变量num的值，每次处理让它+1
# add函数返回的是处理好的num值
# return add，就是返回了这个地址值
# 郝健成 = auto_num(10)
# print(郝健成)
# print(郝健成()) # 1  用赋值好变量调用+()，就是调用add()函数
# print(郝健成()) # 2
# print(郝健成()) # 3
# print(郝健成()) # 4

def auto_num1(num):
    def add():
        nonlocal num
        num+=1
        return num
    return add()

# print(auto_num1(10)) # 11
# print(auto_num1(10)) # 11
# print(auto_num1(10)) # 11
# print(auto_num1(10)) # 11

# 装饰器
def run(): # 源代码
    print("跑步")

# run()
# 还是run方法，我想加一个健身
"""def run():
    print("跑步")
    print("健身")# 这样是不对的，相当于重写了这个方法；这个不是装饰器"""
# run()
'''
男孩1嫌弃女朋友丑 带女朋友去买衣服 项链和化妆品 变的更加自信 
原来的外貌 原来的性格 没有发生改变 :装饰器

男孩2嫌弃女朋友丑 带女朋友去整容 变的更加自信(万一失败呢？) 
原来的外貌 原来的性格发现改变 ： 不是装饰器
'''
"""name = "好健康"
def run(name):
    print("===================")
    print(f"我是：{name}")
    print("===================")
# run(name)
# 装束器就是一个特殊的闭包函数
def decorate(func):
    def new_func(new_name):
        print("我是被装饰器前面的代码")
        func(new_name)
        print("我是装饰器后面的代码")
    return new_func
new_func = decorate(run)
new_func("琳姐")"""

# 装饰器案例一：自我介绍
def student_info(name):
    print("===================")
    print(f"大家好，我叫：{name}")
    print("===================")
# 写完这个函数，我发现没有介绍我的家庭地址，我的手机号码，我的性别，目前所在地，所以，我重新加一些内容，但是还不能改变原来的方法
def info(func):# func，就是被修饰的方法
    def luoji(name,address,phone_number,mm_address,sex):
        func(name)
        print(f"我的家庭地址是在：{address},我的手机号码是：{phone_number}，我目前所在地是：{mm_address},我的性别是：{sex}")
        print("自我介绍完毕")
    return luoji
# student_info("好健康")
"""s = info(student_info) # s == luoji
s("好健康","辽宁沈阳","1592322312","吉林省","女")"""

# 案例二：时间装饰器案例
from datetime import datetime # 时间处理模块
# 当前时间
# print(datetime.now())# 2025-03-31 17:17:31.812186

n = 900000
# 从1开始加到900000
def for1(n):
    sum = 0
    for i in range(1,n+1):
        sum += i
    print(sum)
def run_time(func): # 计算从1开始加到n的时间是多少
    def new_func(n):
        start_time = datetime.now() #开始时间
        print(f"开始时间：{start_time}")
        func(n)
        end_time = datetime.now()
        print(f"结束时间：{end_time}")
        time1 = end_time - start_time
        print(f"花费时间为：{time1}")
    return new_func
# for1 = run_time(for1)
# for1(n)
"""
代码运行结果：
print(f"开始时间：{start_time}")
print(sum)
print(f"结束时间：{end_time}")
print(f"花费时间为：{time1}")
"""

# 简化装饰器
def run_time1(func): # 计算从1开始加到n的时间是多少
    def new_func(n):
        start_time = datetime.now() #开始时间
        print(f"开始时间：{start_time}")
        func(n)
        end_time = datetime.now()
        print(f"结束时间：{end_time}")
        time1 = end_time - start_time
        print(f"花费时间为：{time1}")
    return new_func
n1 = 900000
@run_time1
def for2(n):
    sum = 0
    for i in range(1,n+1):
        sum +=i
    print(sum)
for2(n1)
















